package com.lsh.ofc.core.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.base.common.exception.BusinessException;
import com.lsh.ofc.core.base.AbstractTask;
import com.lsh.ofc.core.constant.Constants;
import com.lsh.ofc.core.dao.OfcRoDetailDAO;
import com.lsh.ofc.core.entity.*;
import com.lsh.ofc.core.enums.FulfillChannel;
import com.lsh.ofc.core.enums.RoStatus;
import com.lsh.ofc.core.enums.SumFlag;
import com.lsh.ofc.core.enums.WMSOrderType;
import com.lsh.ofc.core.exception.EC;
import com.lsh.ofc.core.service.*;
import com.lsh.ofc.proxy.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

/**
 * 创建RO处理Handler
 *
 * @author huangdong
 * @date 16/9/9
 */
public abstract class CreateRoHandler extends AbstractTask<Boolean> {

    protected final static Logger logger = LoggerFactory.getLogger(CreateRoHandler.class);

    private final OfcRoDetailDAO ofcRoDetailDAO;

    protected final OfcRoService ofcRoService;

    protected final OfcRoCreateService ofcRoCreateService;

    protected final OfcSoService ofcSoService;

    protected final OfcSupplierService ofcSupplierService;

    protected final SupplierConfigService supplierConfigService;

    private final OfcRoHead ro;

    private final OfcCustomer customer;

    protected CreateRoHandler(final ApplicationContext context, final OfcRoHead ro, final OfcCustomer customer) {
        Assert.notNull(context, "context can not be null!");
        Assert.notNull(ro, "ro can not be null!");
        Assert.notNull(customer, "customer can not be null!");
        this.ro = ro;
        this.customer = customer;
        this.ofcRoDetailDAO = context.getBean(OfcRoDetailDAO.class);
        this.ofcRoService = context.getBean(OfcRoService.class);
        this.ofcRoCreateService = context.getBean(OfcRoCreateService.class);
        this.ofcSoService = context.getBean(OfcSoService.class);
        this.supplierConfigService = context.getBean(SupplierConfigService.class);
        this.ofcSupplierService = context.getBean(OfcSupplierService.class);
    }

    @Override
    public Boolean execute() throws Exception {
        if (!RoStatus.UNCREATED.getValue().equals(ro.getRoStatus())) {
            logger.warn("RO状态不是\"待创建\"！RO单号=" + ro.getSoCode() + "，状态=" + ro.getRoStatus());
            return true;
        }
        if (CollectionUtils.isEmpty(this.ro.getDetails())) {
            OfcRoDetail params = new OfcRoDetail();
            params.setRoBillCode(this.ro.getRoBillCode());
            this.ro.setDetails(this.ofcRoDetailDAO.findList(params));
        }
        try {
            return this.process(this.ro, this.customer);
        } catch (Throwable e) {
            logger.error("【" + this.ro.getSoBillCode() + "】创建RO异常" + e.getMessage(), e);
            return false;
        }
    }

    protected abstract boolean process(final OfcRoHead ro, final OfcCustomer customer) throws BusinessException;

    public static CreateRoHandler newInstance(final ApplicationContext context, final OfcRoHead ro, final OfcCustomer customer) throws BusinessException {
        Assert.notNull(context, "context can not be null!");
        Assert.notNull(ro, "ro can not be null!");
        Assert.notNull(customer, "customer can not be null!");
        FulfillChannel channel = FulfillChannel.valueOf(ro.getFulfillChannel());
        if (channel == null) {
            throw EC.ERROR.exception("fulfill channel is not support!!! channel=" + ro.getFulfillChannel());
        }
        try {
            return channel.getCreateRoHandlerType().getDeclaredConstructor(ApplicationContext.class, OfcRoHead.class, OfcCustomer.class).newInstance(context, ro, customer);
        } catch (Exception e) {
            throw EC.ERROR.exception(e);
        }
    }

    protected CreateWgRoReqHead getCreateWgRoReq(String costomerId, OfcSupplier ofcSupplier) {
        CreateWgRoReqHead order = new CreateWgRoReqHead();

        JSONObject roExt = JSON.parseObject(ro.getExt());
//        JSONObject soPre = roExt.getJSONObject("so_pre");

        OfcSupplier supplier = supplierConfigService.findSupplier(
                ro.getSupplierId(), ro.getSupplierCode(), ro.getSupplierGroup(), ro.getSupplierOrg(), ro.getRegionCode(), ro.getSupplierDc());

        if (supplier == null) {
            throw EC.SO_ORDER_IS_ERROR.exception("supplier 信息不存在！请检查");
        }

        JSONObject config = JSON.parseObject(supplier.getConfig());

        String ownerId = config.getString("ownerId");
        if (StringUtils.isEmpty(ownerId)) {
            throw EC.SO_ORDER_IS_ERROR.exception("ownerId 不存在！请检查");
        }

        Integer saleModel = config.getInteger("saleModel");
        Integer deliveryType = config.getInteger("deliveryType");

        order.setWarehouseCode(this.ro.getSupplierDc());
        //原SO单号
        order.setSoId(this.ro.getSoCode());
        // 云仓返仓
        logger.info("ro: {}, supplier id: {}; owner id: {}", new Object[]{ro.getId(), ro.getSupplierId(), ownerId});
        if (deliveryType.equals(3) && saleModel.equals(2)) {
            order.setSoId(null);
            order.setWarehouseCode(this.ro.getSupplierDc());
        }

        List<OfcRoDetail> roDetails = this.ro.getDetails();
        List<CreateWgRoReqDetail> details = new ArrayList<>(roDetails.size());
        BigDecimal roAmount = BigDecimal.ZERO;
        for (OfcRoDetail roDetail : roDetails) {
            CreateWgRoReqDetail detail = new CreateWgRoReqDetail();
            detail.setLineNo(String.valueOf(roDetail.getItemNo()));
            detail.setGoodsId(roDetail.getSkuSupplyCode());
            detail.setQty(roDetail.getSkuReturnQty());
            //TODO:箱规,默认写1
            detail.setUnit("1.00");
            detail.setGoodsAmount(roDetail.getGoodsAmount().setScale(2, BigDecimal.ROUND_UP));
            details.add(detail);

            roAmount = roAmount.add(roDetail.getGoodsAmount());
        }

        order.setOwnerId(ownerId);
        order.setOrderId(this.ro.getRoBillCode());
        order.setCustomerId(costomerId);
        order.setOrderCustomerName(this.customer.getCustName());
        order.setOrderCustomerId(this.customer.getMpCustCode());
        order.setVenderId(this.ro.getSupplierId() + "");
        order.setItems(details);
        order.setMisVenderId(this.ro.getVenderId());
        order.setOrderAmount(roAmount.setScale(2, BigDecimal.ROUND_UP));

        JSONObject ext = new JSONObject();
        ext.put("oms_return_order_id", this.ro.getOrderCode());
        ext.put("oms_return_id", this.ro.getReturnCode());
        Integer returnOrderType = roExt.getInteger("return_order_type");
        if (returnOrderType != null) {
            ext.put("return_order_type", returnOrderType);
        }
        order.setRsoExt(ext.toJSONString());

        return order;
    }


    protected CreateLshRoReqHead getCreateLshRoReq() {
        CreateLshRoReqHead order = new CreateLshRoReqHead();
        order.setWarehouseCode(this.ro.getSupplierDc());
        //返仓业务单号
        order.setOrderOtherId(this.ro.getRoBillCode());
        //原SO单号
        order.setOrderOtherRefId(this.ro.getSoBillCode());
        Integer ownerUid = this.ro.getSupplierOrg();
        //TODO wms 货主
        if (ownerUid == 3) {
            ownerUid = 2;
        }
        order.setOwnerUid(Long.valueOf(ownerUid));
        order.setOrderType(WMSOrderType.Return.getCode());
        order.setOrderUser(this.customer.getMpCustCode());
        order.setSupplierCode("0");
        order.setOrderTime(new Date(this.ro.getCreateTime() * 1000L));
        order.setEndDeliveryDate(null);
        order.setSourceSystem("2");

        List<OfcRoDetail> roDetails = this.ro.getDetails();
        List<CreateLshRoReqDetail> details = new ArrayList<>(roDetails.size());
        for (OfcRoDetail roDetail : roDetails) {
            CreateLshRoReqDetail detail = new CreateLshRoReqDetail();
            detail.setDetailOtherId(String.valueOf(roDetail.getItemNo()));
            detail.setSkuCode(roDetail.getSkuSupplyCode());
            detail.setBarCode("");
            detail.setOrderQty(roDetail.getSkuReturnQty());
            //TODO:箱规,默认写1
            detail.setPackUnit(new BigDecimal("1.00"));
            detail.setPackName("EA");
            detail.setPrice(new BigDecimal("0.000"));
            detail.setUnitName("EA");
            detail.setUnitQty(roDetail.getSkuReturnQty());
            details.add(detail);
        }

        order.setDetailList(details);
        return order;
    }

    protected CreateSoReqHead getCreateRoReq(OfcSoHead ofcSoHead) {
        Map<String, OfcSoDetail> supplyDetailMap = new HashMap<>((int) (this.ro.getDetails().size() / 0.75) + 1);
        for (OfcSoDetail detail : ofcSoHead.getDetails()) {
            supplyDetailMap.put(detail.getSkuSupplyCode(), detail);
        }

        String orderCode;
        JSONObject soExt = JSON.parseObject(ofcSoHead.getExt());
        String sumFlag = soExt.getString(Constants.ORDER_H_SUM_FLAG);
        if (!StringUtils.isEmpty(sumFlag) && sumFlag.equals(SumFlag.SUM.getCode())) {
            String sumSoId = soExt.getString(Constants.ORDER_H_SUM_SOID);
            if (StringUtils.isEmpty(sumSoId)) {
                throw EC.SO_ORDER_IS_ERROR.exception("sumSoId值不存在！请检查");
            }
            orderCode = sumSoId;
        } else {
            orderCode = this.ro.getSoBillCode();
        }

        CreateSoReqHead order = new CreateSoReqHead();
        order.setSoCode(this.ro.getSoCode());
        order.setOrderCode(orderCode);
        order.setWarehouse(this.ro.getSupplierDc());
        order.setRegionCode(this.ro.getRegionCode());
        order.setSoUserCode(this.customer.getMpCustCode());
        order.setFulfillWms(this.ro.getFulfillWms());

        order.setSupplierOrg(this.ro.getSupplierOrg());
        order.setSupplierId(this.ro.getSupplierId());

        List<OfcRoDetail> items = this.ro.getDetails();
        List<CreateSoReqDetail> details = new ArrayList<>(items.size());
        DecimalFormat format = new DecimalFormat("000000");
        for (OfcRoDetail item : items) {
            OfcSoDetail soDetail = supplyDetailMap.get(item.getSkuSupplyCode());
            if (soDetail == null) {
                throw EC.SO_DETAILS_IS_EMPTY.exception("查询不到该【" + item.getSkuSupplyCode() + "】的so detail信息");
            }

            CreateSoReqDetail detail = new CreateSoReqDetail();
            detail.setItemNum(format.format(item.getItemNo()));
            detail.setSkuCode(item.getSkuSupplyCode());
            detail.setQuality(item.getSkuReturnQty());
            detail.setAmount(item.getGoodsAmount());
            detail.setExt(soDetail.getExt());
            details.add(detail);
        }
        order.setDetails(details);
        return order;
    }
}
